package com.shux.inventory.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.shux.inventory.biz.IRequestAsynProcessBiz;
import com.shux.inventory.biz.InventoryProductBiz;
import com.shux.inventory.entity.InventoryProduct;
import com.shux.inventory.request.InventoryQueryCacheRequest;
import com.shux.inventory.request.Request;

@Controller
public class InventoryProductQueryCacheController {
	private @Autowired InventoryProductBiz inventoryProductBiz;
	private @Autowired IRequestAsynProcessBiz  requestAsynProcessBiz;
	@RequestMapping("/queryInventoryProduct")
	@ResponseBody
	public InventoryProduct queryInventoryProduct(Integer productId){
		Request request = new InventoryQueryCacheRequest(productId,inventoryProductBiz,false);
		requestAsynProcessBiz.process(request);
		InventoryProduct inventoryProduct = null;
		long beginTime = System.currentTimeMillis();
		long alltime = 0L;
		long endTime = 0L;
		try {
			while (true) {
				alltime = endTime - beginTime;
				if (alltime > 200) {//如果等了200毫秒还不能获取到数据，则从数据库查询
					break;
				}
				inventoryProduct = inventoryProductBiz
						.loadInventoryProductCache(productId);
				if (inventoryProduct != null) {
					return inventoryProduct;
				}
				Thread.sleep(20);//如果没有获得到缓存则先等20毫秒在去获取
				endTime = System.currentTimeMillis();
			}
			/**
			 * 代码执行到这里有以下几种情况
			 * 1、数据库中本来就没有数据（数据穿透），但标志位已经表示为false
			 * 2、前几次查询的都积压在队列中，导致缓存中没有数据或者查询数据库比较慢，还没有刷新到缓存中，但标志位还是false
			 * 3、上次有数据查询请求，也把数据刷新到了缓存，但由于缓存满了，
			 * redis通过LRU清除了，导致标志位还是false，但缓存中没有数据了，所以就运行到这里来了。
			 */
			inventoryProduct = inventoryProductBiz.loadInventoryProductByProductId(productId);
			if (inventoryProduct != null) {
				Request requestRefresh = new InventoryQueryCacheRequest(productId,inventoryProductBiz,true);
				requestAsynProcessBiz.process(requestRefresh);//强制刷新缓存
			}
		} catch (Exception e) {
			
		}
		return inventoryProduct;
	}
}
